/*
 * @brief
 * @author li yong (DogLee)
 * @email 20162439@qq.com
 * @version 1.0
 * @date 2018-08-03 11:21:53
 */
#include "logappenderfile.h"

#include <QFileInfo>
#include <QTimer>
#include <QDir>

#include <QMutex>
#include <QThread>

Q_GLOBAL_STATIC(QMutex, lock)


// 日志文件目录
#define LOG_DIR             "./log/"

// 日志文件名字
#define LOG_NAME            "monitorlog.txt"

// 单个日志文件大小
#define LOG_FILE_SIZE       (5 * 1024 * 1024)   // 5M

// log文件数量，最多不超过文件数量。
// 当单个日志文件满时，将重命名日志文件，并增加后缀".1"。例如：monitorlog.txt.1。
#define LOG_FILE_COUNTS     3

LogAppenderFile::LogAppenderFile() : ILogAppender()
{
    setLogPath(LOG_DIR);
    logFileName = LOG_NAME;
    logFile.setFileName(logPath + logFileName);
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(onDump()));
    timer->start(500);
}

LogAppenderFile::~LogAppenderFile()
{
    if (timer)
        delete timer;
}

void LogAppenderFile::append(const DebugMessage &message)
{
    if (message.content.contains("Could not read from input device (No such device)"))
        return;

    lock()->lock();
    messages.append(message);
    lock()->unlock();

    if (messages.size() > 100)
        onDump();

}

void LogAppenderFile::setLogPath(const QString &path)
{
    logPath = path;

    QDir dir(logPath);
    if (!dir.exists())
        dir.mkpath(logPath);
}

void LogAppenderFile::setLogName(const QString &name)
{
    logFileName  = name;
}

void LogAppenderFile::onDump()
{
    QMutexLocker locker(lock());
    if (messages.empty())
        return;

    if (!logFile.isOpen())
        logFile.open(QIODevice::ReadWrite | QIODevice::Append);

    if (logFile.isOpen())
    {
        QTextStream out(&logFile);
        foreach (auto message, messages)
        {
            QString str = message.time + "[" + messageTypeCode(message.type) + "]" + message.context;
            str += " -> " + message.content;
            out << str << endl;
        }
        logFile.close();
    }
    messages.clear();

    if (isFull())
        rotate();
}

bool LogAppenderFile::isFull() const
{
    bool full = false;
    QFileInfo info(logFile.fileName());
    if (info.size() > LOG_FILE_SIZE)
    {
        full = true;
    }

    return full;
}

void LogAppenderFile::rotate()
{
    if (!logFile.isOpen())
        logFile.open(QIODevice::ReadWrite | QIODevice::Append);

    if (logFile.isOpen())
    {
        QTextStream out(&logFile);
        out << "This log file is full, so will rorate." << endl;
        logFile.close();
    }

    int num = LOG_FILE_COUNTS;
    for (int i = num - 1; i > 0; i--)
    {
        QString destname = QString("%1%2.%3").arg(logPath).arg(logFileName).arg(i);
        QString oriname;
        if (i == 1)
            oriname = QString("%1%2").arg(logPath).arg(logFileName);
        else
            oriname = QString("%1%2.%3").arg(logPath).arg(logFileName).arg(i - 1);

        if (QFile::exists(destname))
            QFile::remove(destname);

        QFile::rename(oriname, destname);
    }
}
